/*
 * @Author: cooper
 * @Date: 2025-04-08 15:10:19
 * @Wechat: cmd_develop
 * @Description:
 */

#include "mds_hex.h"

/// @brief 读取电机位置 reply:06H
/// @param tx_data
/// @param addr
/// @return
u8 mds_moto_get_distance(u8 *tx_data, u8 const addr)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x04;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x31;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x03;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/// @brief 读取电机实时转速
/// @param tx_data
/// @param addr
/// @return
u8 mds_moto_get_speed(u8 *tx_data, u8 const addr)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x04;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x32;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x01;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/// @brief 设置电机限位归零
/// @param tx_data
/// @param addr
/// @return
u8 mds_moto_set_home(u8 *tx_data, u8 const addr)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x06;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x91;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x01;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/// @brief 相对运动
/// @param tx_data 指令指针
/// @param addr 地址
/// @return 指令数量
u8 mds_moto_set_rel(u8 *tx_data, u8 addr, u16 speed, u16 acc, u32 relAxis)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x10;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0xF4;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x04;
    tx_data[i++] = 0x08;
    /*加速度*/
    tx_data[i++] = (acc >> 8) & 0xff;
    tx_data[i++] = (acc >> 0) & 0xff;
    /*速度*/
    tx_data[i++] = (speed >> 8) & 0xff;
    tx_data[i++] = (speed >> 0) & 0xff;
    /*相对坐标*/
    tx_data[i++] = (relAxis >> 24) & 0xff;
    tx_data[i++] = (relAxis >> 16) & 0xff;
    tx_data[i++] = (relAxis >> 8) & 0xff;
    tx_data[i++] = (relAxis >> 0) & 0xff;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/// @brief 绝对运动
/// @param tx_data 指令指针
/// @param addr 地址
/// @return 指令数量
u8 mds_moto_set_abs(u8 *tx_data, u8 addr, u16 speed, u16 acc, u32 absAxis)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x10;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0xF5;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x04;
    tx_data[i++] = 0x08;
    /*加速度*/
    tx_data[i++] = (acc >> 8) & 0xff;
    tx_data[i++] = (acc >> 0) & 0xff;
    /*速度*/
    tx_data[i++] = (speed >> 8) & 0xff;
    tx_data[i++] = (speed >> 0) & 0xff;
    /*绝对坐标*/
    tx_data[i++] = (absAxis >> 24) & 0xff;
    tx_data[i++] = (absAxis >> 16) & 0xff;
    tx_data[i++] = (absAxis >> 8) & 0xff;
    tx_data[i++] = (absAxis >> 0) & 0xff;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/// @brief 设置电机堵转功能
/// @param tx_data
/// @param addr 地址
/// @param fig 1：开启保护 0：关闭保护
/// @return
u8 mds_moto_set_protect(u8 *tx_data, u8 const addr, u8 const fig)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x06;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x88;
    tx_data[i++] = 0x00;
    if (fig)
    {
        tx_data[i++] = 0x01;
    }
    else
    {
        tx_data[i++] = 0x00;
    }
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/**  03读取寄存器,用于读取温控板的状态
 * @brief  	主机 03 功能码通讯
 * @param1  	发送缓冲区指针
 * @param2  	从机地址
 * @param3  	寄存器地址
 * @param4  	数据
 * @retval 	数据长度
 */
u8 MASTER_MODBUS_03_CODE(u8 *const tx_buffer, u8 const slave_addr, u16 const registe_address, u16 const data)
{
    u16 crc16 = 0;
    u8 len = 0;
    tx_buffer[len++] = slave_addr; // 地址
    tx_buffer[len++] = 0x03;       // 功能
    /* 寄存器地址 */
    tx_buffer[len++] = registe_address / 256;
    tx_buffer[len++] = registe_address % 256;
    /* 数据 */
    tx_buffer[len++] = data / 256;
    tx_buffer[len++] = data % 256;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_buffer, 6);
    tx_buffer[len++] = crc16 % 256;
    tx_buffer[len++] = crc16 / 256;
    return len;
}

/// @brief
/// @param tx_buffer
/// @param slave_addr 继电器的地址，2.0系统是01
/// @param pos 继电器的位置，从0开始算
/// @param data 01是工作，00是释放
/// @return
u8 MASTER_MODBUS_06_CODE(u8 *const tx_buffer, u8 const slave_addr, u8 pos, u16 const data)
{
    u16 crc16 = 0;
    u8 len = 0;
    tx_buffer[len++] = slave_addr; // 地址
    tx_buffer[len++] = 0x06;       // 功能
    /* 寄存器地址 */
    tx_buffer[len++] = pos / 256;
    tx_buffer[len++] = pos % 256;
    /* 数据 */
    tx_buffer[len++] = data / 256;
    tx_buffer[len++] = data % 256;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_buffer, 6);
    tx_buffer[len++] = crc16 % 256;
    tx_buffer[len++] = crc16 / 256;
    return len;
}
/**
 * @brief  	主机 10 功能码通讯
 * @param1  	发送缓冲区指针
 * @param2  	几号烤管
 * @param3  	烤制温度
 * @param4  	烤制时间
 * @param5  	保温温度
 * @param6  	保温时间
 * 地址1 功能码1 寄存器地址2 寄存器数量2 字节数1 烤制温度2 烤制时间2 保温温度2 保温时间2 校验码2
 * @retval 	数据长度
 */
u8 MASTER_MODBUS_10_CODE(u8 *const tx_buffer, u8 const pipe_addr, u16 bake_temp, u16 bake_time, u16 keep_temp, u16 keep_time)
{
    u16 crc16 = 0;
    u8 len = 0;
    u8 slave_addr;
    u8 temptemp_add; // 温控板的地址012

    slave_addr = ((pipe_addr - 1) / 3) + 1;
    temptemp_add = (pipe_addr - 1) % 3;

    u8 registe_address = temptemp_add + 30; // 寄存器地址，对应温控板
    tx_buffer[len++] = slave_addr;          // 地址
    tx_buffer[len++] = 0x10;                // 功能
    // 寄存器地址
    tx_buffer[len++] = registe_address / 256;
    tx_buffer[len++] = registe_address % 256;
    // 寄存器数量 烤制温度 烤制时间 保温温度 保温时间
    tx_buffer[len++] = 4 / 256;
    tx_buffer[len++] = 4 % 256;
    // 数据个数 字节数  1个数据 然后再乘以寄存器数量
    tx_buffer[len++] = 1 * 4;
    // 烤制温度
    tx_buffer[len++] = bake_temp / 256;
    tx_buffer[len++] = bake_temp % 256;
    // 烤制时间
    tx_buffer[len++] = bake_time / 256;
    tx_buffer[len++] = bake_time % 256;
    // 保温温度
    tx_buffer[len++] = keep_temp / 256;
    tx_buffer[len++] = keep_temp % 256;
    // 保温时间
    tx_buffer[len++] = keep_time / 256;
    tx_buffer[len++] = keep_time % 256;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_buffer, len);
    tx_buffer[len++] = crc16 % 256;
    tx_buffer[len++] = crc16 / 256;
    return len;
}

/**
 * @brief  	主机 10 功能码通讯
 * @param1  	发送缓冲区指针
 * @param2  	温度值1
 * @param2  	温度值2
 * @param3  	read_write 0是读，1是写
 * @retval
 */
u8 ICE_TEMP_CODE(u8 *const tx_buffer, u8 temp1, u8 temp2, u8 read_write)
{
    u8 len = 0;
    u8 crc8 = 0;
    tx_buffer[len++] = 0x5a;                 // 启动字符
    tx_buffer[len++] = 0x01;                 // 分组域
    tx_buffer[len++] = 0x01;                 // 机器地址
    tx_buffer[len++] = 0x00;                 // 柜内温度
    tx_buffer[len++] = 0x00;                 // 柜内温度
    tx_buffer[len++] = 0x00;                 // 门开关
    tx_buffer[len++] = 0x00;                 // 冷凝温度1
    tx_buffer[len++] = 0x00;                 // 冷凝温度2
    tx_buffer[len++] = 0x00;                 // 蒸发温度1
    tx_buffer[len++] = 0x00;                 // 蒸发温度2
    tx_buffer[len++] = 0x00;                 // 状态标志 1
    tx_buffer[len++] = 0x00 | read_write;    // 状态标志 2
    tx_buffer[len++] = 0x00;                 // 状态标志 3
    tx_buffer[len++] = 0x00;                 // 参数地址
    tx_buffer[len++] = temp1;                // 参数值1
    tx_buffer[len++] = temp2;                // 参数值2
    tx_buffer[len++] = 0x00;                 // 版本号
    crc8 = getCheckSumMAXIM(tx_buffer, len); // 校验和 getCheckSumMAXIM
    tx_buffer[len++] = crc8;

    return len;
}

/// @brief 设置电机modbus_rtu功能
/// @param tx_data
/// @param addr 地址
/// @param distant 回零后的返回距离
/// @return
u8 mds_moto_set_modbusRTU(u8 *tx_data, u8 const addr)
{
    u8 i = 0;
    tx_data[i++] = 0xFA;
    tx_data[i++] = addr;
    tx_data[i++] = 0x8E;
    tx_data[i++] = 0x01;
    tx_data[i++] = 0x89 + addr;
    return i;
}

/// @brief 取消电机modbus_rtu功能
/// @param tx_data
/// @param addr
/// @return
u8 mds_moto_cancel_modbusRTU(u8 *tx_data, u8 const addr)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x06;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x8E;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x00;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}

/// @brief 设置电机无限位回零参数
/// @param tx_data
/// @param addr 地址
/// @param distant 回零后的返回距离
/// @return
u8 mds_moto_set_zero_pos(u8 *tx_data, u8 const addr, u32 distant)
{
    u8 i = 0;
    u16 crc16 = 0;
    tx_data[i++] = addr;
    tx_data[i++] = 0x10;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x94;
    tx_data[i++] = 0x00;
    tx_data[i++] = 0x04;
    tx_data[i++] = 0x08;
    tx_data[i++] = (distant >> 24) & 0xff;
    tx_data[i++] = (distant >> 16) & 0xff;
    tx_data[i++] = (distant >> 8) & 0xff;
    tx_data[i++] = distant & 0xff;
    tx_data[i++] = 0;
    // u16 hm_mode:0有限位开关回零，1无限位开关回零
    tx_data[i++] = 1;
    tx_data[i++] = 0;
    // u16 hm_ma:无限位回零电流，57默认800mA,42默认400mA
    tx_data[i++] = 800 >> 8;
    tx_data[i++] = 800 & 0xff;
    /* CRC校验 */
    crc16 = usMBCRC16(tx_data, i);
    tx_data[i++] = crc16 % 256;
    tx_data[i++] = crc16 / 256;
    return i;
}
